// ----------------------------------------------------------------------------
// diabindLoader.cpp
// Load debug information
// ----------------------------------------------------------------------------

#include "stdafx.h"

#include "diabindLoader.h"

namespace diabind
{

// ----------------------------------------------------------------------------

namespace
{

// ----------------------------------------------------------------------------

class CComInitializer : protected boost::noncopyable
{
public:
    CComInitializer();
    ~CComInitializer();
};

// ----------------------------------------------------------------------------

CComInitializer::CComInitializer()
{
    HRESULT hResult = ::CoInitialize(NULL);
    if (FAILED(hResult))
        throw CException(hResult, "CoInitialize");
}

// ----------------------------------------------------------------------------

CComInitializer::~CComInitializer()
{
    ::CoUninitialize();
}

// ----------------------------------------------------------------------------

}   // namespace <nameless>

// ----------------------------------------------------------------------------

std::unique_ptr< CComInitializer > g_ComInitializer;

// ----------------------------------------------------------------------------

CSessionPtr CLoader::FromPdb(const std::wstring &wstrFilePath)
{
    // not thread-safe
    if (!g_ComInitializer.get())
        g_ComInitializer.reset( new CComInitializer );

    typedef CSessionPtr (*LoadRoutinePtr)(const std::wstring &);
    static LoadRoutinePtr arrLoaders[] = 
    {
        &CLoader::FromPdb120,
        &CLoader::FromPdb110,
        &CLoader::FromPdb100,
        &CLoader::FromPdb90,
        &CLoader::FromPdb80
    };

    for (size_t i = 0; i < _countof(arrLoaders); ++i)
    {
        try
        {
            return arrLoaders[i](wstrFilePath);
        }
        catch(const CDiaSourceNotRegistered &Exception)
        {
            UNREFERENCED_PARAMETER(Exception);
        }
    }

    throw CException(REGDB_E_CLASSNOTREG, "::CoCreateInstance");
}

// ----------------------------------------------------------------------------

CSessionPtr CLoader::FromExe(const std::wstring &wstrFilePath, const std::wstring &wstrSearchPath)
{
    // not thread-safe
    if (!g_ComInitializer.get())
        g_ComInitializer.reset( new CComInitializer );

    typedef CSessionPtr (*LoadRoutinePtr)(const std::wstring &, const std::wstring &);
    static LoadRoutinePtr arrLoaders[] = 
    {
        &CLoader::FromExe120,
        &CLoader::FromExe110,
        &CLoader::FromExe100,
        &CLoader::FromExe90,
        &CLoader::FromExe80
    };

    for (size_t i = 0; i < _countof(arrLoaders); ++i)
    {
        try
        {
            return arrLoaders[i](wstrFilePath, wstrSearchPath);
        }
        catch(const CDiaSourceNotRegistered &Exception)
        {
            UNREFERENCED_PARAMETER(Exception);
        }
    }

    throw CException(REGDB_E_CLASSNOTREG, "::CoCreateInstance");
}


// ----------------------------------------------------------------------------

}   // namespace diabind

// ----------------------------------------------------------------------------

